import json
from functools import partial
from rest_framework.renderers import JSONRenderer

from rest_framework import status
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from rest_framework.generics import RetrieveAPIView

from core.renderers import CSSRenderer

from core import models, serializers, utils


class FontViewSet(ModelViewSet):
    http_method_names = ['get']

    lookup_field = 'name'

    queryset = models.Font.objects.prefetch_related(
        'files'
    ).all()

    serializer_class = serializers.FontSerializer


class FontCSSView(RetrieveAPIView):
    queryset = models.Font.objects.prefetch_related(
        'files',
        'files__unicode_ranges'
    )

    lookup_field = 'name'

    serializer_class = partial(
        serializers.FontSerializer,
        expand=('files', 'files.unicode_ranges')
    )

    renderer_classes = (CSSRenderer, JSONRenderer)

    def retrieve(self, request, *args, **kwargs):
        font = self.get_object()

        query = request.GET

        query_s = serializers.FontCSSQuerySerializer(
            data=query,
            context=self.get_serializer_context()
        )

        if not query_s.is_valid():
            return Response(
                json.dumps(query_s.errors),
                content_type='application/json'
            )

        serializer = self.get_serializer(font)

        data = serializer.data

        body = query_s.data

        name = body['name']

        style = body['style']

        weight = body['weight']

        try:
            css = utils.font_to_css(data, name, style, weight)
        except ValueError as e:
            return Response(
                json.dumps({
                    'detail': str(e)
                }),
                status=status.HTTP_400_BAD_REQUEST,
                content_type='application/json'
            )

        return Response(css)
